package com.weixin.service.Impl;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import com.weixin.converter.OrderMaster2OrderDtoConverter;
import com.weixin.dao.OrderDetailMapper;
import com.weixin.dao.OrderMasterMapper;
import com.weixin.enums.OrderStatusEnum;
import com.weixin.enums.PayStatusEnum;
import com.weixin.pojo.OrderDetail;
import com.weixin.pojo.OrderMaster;
import com.weixin.pojo.ProductInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.weixin.dto.CartDto;
import com.weixin.dto.OrderDto;
import com.weixin.enums.ResultEnum;
import com.weixin.exception.SellException;
import com.weixin.service.OrderMasterService;
import com.weixin.service.ProductInfoService;
import com.weixin.util.KeyUtil;

/**
 * 订单表
 * 
 * @author Code generator by CJunGod
 *
 */
@Slf4j
@Service
@Transactional
public class OrderMasterServiceImpl implements OrderMasterService {
	
	@Resource
	private OrderMasterMapper orderMasterMapper;
	
	@Resource
	private ProductInfoService productInfoService;
	
	@Resource
	private OrderDetailMapper orderDetailMapper;

	@Override
	public OrderDto createOrder(OrderDto orderDto) {
		// TODO Auto-generated method stub
		String orderId = KeyUtil.genUniqueKey();
		BigDecimal orderAmount = new BigDecimal(BigInteger.ZERO);
		
		for(OrderDetail detail : orderDto.getOrderDetailList()) {
			ProductInfo productInfo = productInfoService.findById(detail.getProductId());
			if(productInfo == null) {
				throw new SellException(ResultEnum.PRODUCT_NOT_EXIST);
			}
			
			orderAmount = productInfo.getProductPrice()
							.multiply(new BigDecimal(detail.getProductQuantity()))
							.add(orderAmount);
			
			detail.setDetailId(KeyUtil.genUniqueKey());
			detail.setOrderId(orderId);
			BeanUtils.copyProperties(productInfo, detail);
			orderDetailMapper.save(detail);
		}
		
		OrderMaster master = new OrderMaster();
		orderDto.getMaster().setOrderId(orderId);
		BeanUtils.copyProperties(orderDto.getMaster(), master);
		master.setOrderAmount(orderAmount);
		master.setOrderStatus(OrderStatusEnum.NEW.getCode());
		master.setPayStatus(PayStatusEnum.WAIT.getCode());
		orderMasterMapper.save(master);
		
		List<CartDto> cartDtos = orderDto.getOrderDetailList().stream().map(e ->
									new CartDto(e.getProductId(), e.getProductQuantity())
									).collect(Collectors.toList());
		
		productInfoService.decreaseStock(cartDtos);
		return orderDto;
	}

	@Override
	public OrderDto findOne(String orderId) {
		// TODO Auto-generated method stub
		Optional<OrderMaster> byId = orderMasterMapper.findById(orderId);
		if(byId.isPresent()){
			List<OrderDetail> byOrderId = orderDetailMapper.findByOrderId(orderId);
			if(byOrderId.isEmpty()){
				throw new SellException(ResultEnum.ORDERDETAIL_NOT_EXIST);
			}
			OrderDto orderDto = new OrderDto();

			orderDto.setMaster(byId.get());
			orderDto.setOrderDetailList(byOrderId);

			return orderDto;
		}else {
			throw new SellException(ResultEnum.ORDER_NOT_EXIST);
		}

	}

	@Override
	public Page<OrderDto> findList(String buyerOpenid, Pageable pageable) {
		// TODO Auto-generated method stub
		Page<OrderMaster> byBuyerOpenid = orderMasterMapper.findByBuyerOpenid(buyerOpenid, pageable);

		List<OrderDto> convert = OrderMaster2OrderDtoConverter.convert(byBuyerOpenid.getContent());

		return new PageImpl<OrderDto>(convert,pageable,byBuyerOpenid.getTotalElements());
	}

	@Override
	public OrderDto cancel(OrderDto orderDto) {
		// TODO Auto-generated method stub
		if(!orderDto.getMaster().getOrderStatus().equals(OrderStatusEnum.NEW.getCode())){
			log.error("取消订单，订单状态不正确,orderId={},orderStatus={}",orderDto.getMaster().getOrderId(),orderDto.getMaster().getOrderStatus());
			throw  new SellException(ResultEnum.ORDER_STATUS_ERROR);
		}

		orderDto.getMaster().setOrderStatus(OrderStatusEnum.CANCEL.getCode());
		OrderMaster updateResult = orderMasterMapper.save(orderDto.getMaster());
		if(updateResult == null){
			log.error("取消订单 更新失败,orderMaster={}",orderDto.getMaster());
			throw new SellException(ResultEnum.ORDER_UPDATE_ERROR);
		}

		if(orderDto.getOrderDetailList().isEmpty()){
			log.error("{取消订单}订单中无商品详情,orderDto={}",orderDto);
			throw new SellException(ResultEnum.ORDER_DETAIL_EMPTY);
		}

		List<CartDto> collect = orderDto.getOrderDetailList().stream().map(o ->
				new CartDto(o.getProductId(), o.getProductQuantity())
		).collect(Collectors.toList());
		productInfoService.increaseStock(collect);

		if(orderDto.getMaster().getPayStatus().equals(PayStatusEnum.SUCCESS.getCode())){
			//TODO
		}
		return orderDto;
	}

	@Override
	public OrderDto finish(OrderDto orderDto) {
		// TODO Auto-generated method stub
		if(!orderDto.getMaster().getOrderStatus().equals(OrderStatusEnum.NEW.getCode())){
			log.error("{完结订单}订单状态不正确，orderId={},orderStatus={}",orderDto.getMaster().getOrderId(),orderDto.getMaster().getOrderStatus());
			throw new SellException(ResultEnum.ORDER_STATUS_ERROR);
		}

		orderDto.getMaster().setOrderStatus(OrderStatusEnum.FINISHED.getCode());
		OrderMaster updateResult = orderMasterMapper.save(orderDto.getMaster());
		if(updateResult == null){
			log.error("{完结订单}更新失败，orderMaster={}",orderDto.getMaster());
			throw new SellException(ResultEnum.ORDER_UPDATE_ERROR);
		}
		return orderDto;
	}

	@Override
	public OrderDto paid(OrderDto orderDto) {
		// TODO Auto-generated method stub
		if(!orderDto.getMaster().getOrderStatus().equals(OrderStatusEnum.NEW.getCode())){
			log.error("[订单支付成功][完结订单]订单状态不确定,orderId={},orderStatus={}",orderDto.getMaster().getOrderId(),orderDto.getMaster().getOrderStatus());
			throw new SellException(ResultEnum.ORDER_STATUS_ERROR);
		}

		if (!orderDto.getMaster().getPayStatus().equals(PayStatusEnum.WAIT.getCode())) {
			log.error("{订单支付状态不正确} ,orderDto={}",orderDto);
			throw new SellException(ResultEnum.ORDER_PAY_STATUS_ERROR);
		}

		orderDto.getMaster().setPayStatus(PayStatusEnum.SUCCESS.getCode());
		OrderMaster updateResult = orderMasterMapper.save(orderDto.getMaster());
		if(updateResult == null){
			log.error("{订单支付状态不正确}更新失败，orderMaster={}",orderDto.getMaster());
			throw new SellException(ResultEnum.ORDER_PAY_STATUS_ERROR);
		}
		return orderDto;
	}


}
